
from Cube.utility.SerialNumberGen import SerialNumberGen

class QObjectPool:
    def __init__(self, name=""):
        self.MyName = name
        self._SyncObjIDGen = SerialNumberGen(start=1)
        self._ASyncObjIDGen = SerialNumberGen(start=1,step=-1)
        self._ID2ObjectDict = {}  # { flag:{ID:Obj, ...}, ... }
        self._Name2IDMap = {}
        self.RecycledIDList = []

    def Add(self, obj, flag, IsSyncObj=True):
        if IsSyncObj:
            objID = self._SyncObjIDGen.Gen()
        else:
            objID = self._ASyncObjIDGen.Gen()
        if flag not in self._ID2ObjectDict.keys():
            # create new flag entry
            self._ID2ObjectDict[flag] = {}
        self._ID2ObjectDict[flag][objID] = obj
        self._Name2IDMapAdd(obj.Name, objID)
        return objID

    def _Name2IDMapAdd(self, name, objID):
        if name:
            self._Name2IDMap[name] = objID

    def Remove(self, obj):
        objID = obj.ID
        for ID2Object in self._ID2ObjectDict.itervalues():
            if ID2Object.has_key(objID):
                del ID2Object[objID]
                self.RecycledIDList.append(objID)
                break

    def ObjectGet(self, objID):
        for ID2Object in self._ID2ObjectDict.itervalues():
            if ID2Object.has_key(objID):
                ret = ID2Object[objID]
                break
        else:
            ret = None
        return ret

    def Name2ID(self, name):
        ret = self._Name2IDMap.get(objID, None)
        return ret

    def destroy(self, flag=None):
        if flag is None:
            # destroy all objects
            for ID2Object in self._ID2ObjectDict.itervalues():
                self._DoID2ObjectDestroy(ID2Object)
                self._SyncObjIDGen = SerialNumberGen(start=1)
            self._ID2ObjectDict = {}
            self._Name2IDMap = {}
        else:
            if self._ID2ObjectDict.has_key(flag):
                ID2Object = self._ID2ObjectDict[flag]
                self._DoID2ObjectDestroy(ID2Object)
                self.RecycledIDList.extend(ID2Object.keys())
                del self._ID2ObjectDict[flag]

    def _DoID2ObjectDestroy(self, ID2Object):
        for obj in ID2Object.itervalues():
            name = obj.Name
            if self._Name2IDMap.has_key(name):
                del self._Name2IDMap[name]
            obj.DoDestroy()

    def IDRecycle(self):
        self._SyncObjIDGen.ValidNumberListAdd([ i>0 for i in self.RecycledIDList])
        self._ASyncObjIDGen.ValidNumberListAdd([ i<0 for i in self.RecycledIDList])
        self.RecycledIDList = []

    def __repr__(self):
        nameString = "(%s)"%(self.MyName) if self.MyName else ""
        retList = [ "ObjectPool%s:"%(nameString) ]
        if self._ID2ObjectDict:
            for (flag,ID2Object) in self._ID2ObjectDict.iteritems():
                retList.append("flag:%s --"%(flag))
                for (ID,obj) in ID2Object.iteritems():
                    nameString = "(%s)"%(obj.Name) if obj.Name else ""
                    retList.append("  %d:%s %s"%(ID, nameString, obj))
        else:
            retList.append("-->EMPTY")
        ret = "\n".join(retList)
        return ret
